"""
Condition（条件变量）通常与一个锁关联。需要在多个Contidion中共享一个锁时，
可以传递一个Lock/RLock实例给构造方法，否则它将自己生成一个RLock实例。
可以认为，除了Lock带有的锁定池外，Condition还包含一个等待池，池中的线程处于状态图中的等待阻塞状态，
直到另一个线程调用notify()/notifyAll()通知；得到通知后线程进入锁定池等待锁定。
Condition():
    acquire(): 线程锁
    release(): 释放锁
    wait(timeout): 线程挂起，直到收到一个notify通知或者超时（可选的，浮点数，单位是秒s）才会被唤醒继续运行。
                    wait()必须在已获得Lock前提下才能调用，否则会触发RuntimeError。
    notify(n=1): 通知其他线程，那些挂起的线程接到这个通知之后会开始运行，默认是通知一个正等待该condition的线程,
                最多则唤醒n个等待的线程。notify()必须在已获得Lock前提下才能调用，否则会触发RuntimeError。notify()不会主动释放Lock。
    notifyAll(): 如果wait状态线程比较多，notifyAll的作用就是通知所有线程

只有一把锁，因此需要判断当前是谁拿到锁了就需要在最开始做个if的判断
然后生产者首先拿到锁进行生产，然后就提醒消费者，因为每次只能生产一个，所以生产者就需要把自己挂起了
接着消费者拿到锁，因为一开始没有东西可以消费，所以消费者将自己挂起了，等待生产d者的唤醒，当被唤醒后立马消费，
消费完成后提醒生产者自己消费完成后，将食物数量置零，随后释放锁，等待生产者的再度唤醒。

"""
import threading


class Foo:
    def __init__(self):
        self.value = 1
        self.con = threading.Condition()
        self.t = 0

    def print1(self):
        while self.value < 100:
            if self.con.acquire():
                print('print1:', self.value)
                self.value += 1
                self.t = 1
                self.con.notify()
                self.con.wait()
                self.con.release()

    def print2(self):
        while self.value < 100:
            if self.con.acquire():
                if self.t == 0:
                    self.con.wait()
                print('print2:', self.value)
                self.value += 1
                self.con.notify()
                self.t = 0
                self.con.release()


if __name__ == '__main__':
    f = Foo()

    t1 = threading.Thread(target=f.print1)
    t2 = threading.Thread(target=f.print2)
    t1.start()
    t2.start()
